//! # 动态配置更新模块
//!
//! 提供配置文件监控、热更新和配置变更通知功能

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;

use async_trait::async_trait;
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use tokio::sync::{mpsc, RwLock, broadcast};
use tokio::time::{interval, Instant};

// 条件导入 chrono
#[cfg(any(feature = "server", feature = "client"))]
use chrono::{DateTime, Utc};

use crate::component::{ConfigurableComponent, ComponentManager};
use crate::error::{ConfigCenterResult, ConfigCenterError};

/// 获取当前时间戳
#[cfg(any(feature = "server", feature = "client"))]
pub fn current_timestamp() -> DateTime<Utc> {
    Utc::now()
}

#[cfg(not(any(feature = "server", feature = "client")))]
pub fn current_timestamp() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs()
}

/// 格式化时间戳为字符串
#[cfg(any(feature = "server", feature = "client"))]
pub fn get_timestamp_string(timestamp: &DateTime<Utc>) -> String {
    timestamp.format("%Y%m%d_%H%M%S").to_string()
}

#[cfg(not(any(feature = "server", feature = "client")))]
pub fn get_timestamp_string(timestamp: &u64) -> String {
    format!("{}", timestamp)
}

/// 配置变更事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigChangeEvent {
    /// 变更类型
    pub change_type: ConfigChangeType,
    /// 配置键
    pub config_key: String,
    /// 旧值
    pub old_value: Option<serde_json::Value>,
    /// 新值
    pub new_value: Option<serde_json::Value>,
    /// 变更时间
    #[cfg(any(feature = "server", feature = "client"))]
    pub timestamp: DateTime<Utc>,
    #[cfg(not(any(feature = "server", feature = "client")))]
    pub timestamp: u64, // Unix 时间戳
    /// 变更来源
    pub source: DynamicConfigSource,
    /// 变更原因
    pub reason: String,
}

/// 配置变更类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ConfigChangeType {
    /// 配置创建
    Created,
    /// 配置更新
    Updated,
    /// 配置删除
    Deleted,
    /// 配置重载
    Reloaded,
}

/// 动态配置来源
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DynamicConfigSource {
    /// 文件系统
    File(PathBuf),
    /// 远程配置中心
    Remote(String),
    /// API调用
    Api(String),
    /// 环境变量
    Environment,
    /// 默认值
    Default,
}

/// 配置监听器接口
#[async_trait]
pub trait ConfigChangeListener: Send + Sync {
    /// 处理配置变更事件
    async fn on_config_change(&self, event: ConfigChangeEvent) -> ConfigCenterResult<()>;
    
    /// 获取监听器名称
    fn listener_name(&self) -> &str;
    
    /// 是否对指定配置键感兴趣
    fn is_interested_in(&self, config_key: &str) -> bool {
        // 默认对所有配置感兴趣
        let _ = config_key;
        true
    }
}

/// 动态配置管理器
pub struct DynamicConfigManager {
    /// 组件管理器
    component_manager: Arc<RwLock<ComponentManager>>,
    /// 配置监听器
    listeners: Arc<RwLock<HashMap<String, Box<dyn ConfigChangeListener>>>>,
    /// 文件监控器
    file_watchers: Arc<RwLock<HashMap<PathBuf, RecommendedWatcher>>>,
    /// 变更事件发送器
    change_sender: broadcast::Sender<ConfigChangeEvent>,
    /// 配置缓存
    config_cache: Arc<RwLock<HashMap<String, (serde_json::Value, Instant)>>>,
    /// 缓存TTL
    cache_ttl: Duration,
}

impl DynamicConfigManager {
    /// 创建新的动态配置管理器
    pub fn new(cache_ttl: Duration) -> Self {
        let (change_sender, _) = broadcast::channel(1000);
        
        Self {
            component_manager: Arc::new(RwLock::new(ComponentManager::new())),
            listeners: Arc::new(RwLock::new(HashMap::new())),
            file_watchers: Arc::new(RwLock::new(HashMap::new())),
            change_sender,
            config_cache: Arc::new(RwLock::new(HashMap::new())),
            cache_ttl,
        }
    }

    /// 注册配置组件
    pub async fn register_component(&self, component: Box<dyn ConfigurableComponent>) -> ConfigCenterResult<()> {
        let mut manager = self.component_manager.write().await;
        manager.register_component(component)
    }

    /// 注册配置监听器
    pub async fn register_listener(&self, listener: Box<dyn ConfigChangeListener>) -> ConfigCenterResult<()> {
        let name = listener.listener_name().to_string();
        let mut listeners = self.listeners.write().await;
        
        if listeners.contains_key(&name) {
            return Err(ConfigCenterError::ValidationError(
                format!("监听器 '{}' 已经注册", name)
            ));
        }
        
        listeners.insert(name, listener);
        Ok(())
    }

    /// 监控配置文件
    pub async fn watch_config_file<P: AsRef<Path>>(&self, path: P) -> ConfigCenterResult<()> {
        let path = path.as_ref().to_path_buf();
        let mut watchers = self.file_watchers.write().await;
        
        if watchers.contains_key(&path) {
            return Ok(()); // 已经在监控
        }

        let change_sender = self.change_sender.clone();
        let path_clone = path.clone();
        
        let (tx, mut rx) = mpsc::channel(100);
        
        let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
            if let Ok(event) = res {
                if let Err(e) = tx.try_send(event) {
                    tracing::warn!("发送文件变更事件失败: {}", e);
                }
            }
        }).map_err(|e| ConfigCenterError::Internal(format!("创建文件监控器失败: {}", e)))?;
        
        watcher.watch(&path, RecursiveMode::NonRecursive)
            .map_err(|e| ConfigCenterError::Internal(format!("监控文件失败: {}", e)))?;
        
        // 启动事件处理任务
        let path_for_task = path_clone.clone();
        tokio::spawn(async move {
            while let Some(event) = rx.recv().await {
                if event.kind.is_modify() || event.kind.is_create() {
                    let change_event = ConfigChangeEvent {
                        change_type: ConfigChangeType::Updated,
                        config_key: path_for_task.to_string_lossy().to_string(),
                        old_value: None,
                        new_value: None,
                        timestamp: current_timestamp(),
                        source: DynamicConfigSource::File(path_for_task.clone()),
                        reason: format!("文件 {:?} 发生变更", path_for_task),
                    };
                    
                    if let Err(e) = change_sender.send(change_event) {
                        tracing::warn!("发送配置变更事件失败: {}", e);
                    }
                }
            }
        });

        watchers.insert(path, watcher);
        Ok(())
    }

    /// 更新配置
    pub async fn update_config(&self, component_name: &str, config_key: &str, value: serde_json::Value) -> ConfigCenterResult<()> {
        let old_value = self.get_cached_config(config_key).await;
        
        // 更新缓存
        {
            let mut cache = self.config_cache.write().await;
            cache.insert(config_key.to_string(), (value.clone(), Instant::now()));
        }
        
        // 创建变更事件
        let change_event = ConfigChangeEvent {
            change_type: if old_value.is_some() { 
                ConfigChangeType::Updated 
            } else { 
                ConfigChangeType::Created 
            },
            config_key: config_key.to_string(),
            old_value,
            new_value: Some(value.clone()),
            timestamp: current_timestamp(),
            source: DynamicConfigSource::Api("dynamic_config_manager".to_string()),
            reason: format!("API更新组件 '{}' 的配置", component_name),
        };
        
        // 通知监听器
        self.notify_listeners(&change_event).await?;
        
        // 发送广播事件
        if let Err(e) = self.change_sender.send(change_event) {
            tracing::warn!("发送配置变更广播失败: {}", e);
        }
        
        Ok(())
    }

    /// 获取缓存的配置
    async fn get_cached_config(&self, config_key: &str) -> Option<serde_json::Value> {
        let cache = self.config_cache.read().await;
        
        if let Some((value, timestamp)) = cache.get(config_key) {
            if timestamp.elapsed() < self.cache_ttl {
                return Some(value.clone());
            }
        }
        
        None
    }

    /// 通知所有监听器
    async fn notify_listeners(&self, event: &ConfigChangeEvent) -> ConfigCenterResult<()> {
        let listeners = self.listeners.read().await;
        
        for (name, listener) in listeners.iter() {
            if listener.is_interested_in(&event.config_key) {
                if let Err(e) = listener.on_config_change(event.clone()).await {
                    tracing::error!("监听器 '{}' 处理配置变更失败: {}", name, e);
                    // 不中断其他监听器的处理
                }
            }
        }
        
        Ok(())
    }

    /// 订阅配置变更事件
    pub fn subscribe_changes(&self) -> broadcast::Receiver<ConfigChangeEvent> {
        self.change_sender.subscribe()
    }

    /// 启动定期缓存清理
    pub async fn start_cache_cleanup(&self) {
        let cache = self.config_cache.clone();
        let ttl = self.cache_ttl;
        
        tokio::spawn(async move {
            let mut interval = interval(Duration::from_secs(300)); // 每5分钟清理一次
            
            loop {
                interval.tick().await;
                
                let mut cache_guard = cache.write().await;
                let now = Instant::now();
                
                cache_guard.retain(|_, (_, timestamp)| {
                    now.duration_since(*timestamp) < ttl
                });
                
                let remaining = cache_guard.len();
                drop(cache_guard);
                
                tracing::debug!("配置缓存清理完成，剩余 {} 项", remaining);
            }
        });
    }

    /// 重载组件配置
    pub async fn reload_component_config(&self, component_name: &str) -> ConfigCenterResult<()> {
        let component_manager = self.component_manager.read().await;
        
        if let Some(component) = component_manager.get_component(component_name) {
            let current_config = component.get_config().await?;
            
            let change_event = ConfigChangeEvent {
                change_type: ConfigChangeType::Reloaded,
                config_key: component_name.to_string(),
                old_value: Some(current_config.as_json()?),
                new_value: Some(current_config.as_json()?),
                timestamp: current_timestamp(),
                source: DynamicConfigSource::Api("reload".to_string()),
                reason: format!("重载组件 '{}' 的配置", component_name),
            };
            
            self.notify_listeners(&change_event).await?;
            
            if let Err(e) = self.change_sender.send(change_event) {
                tracing::warn!("发送配置重载事件失败: {}", e);
            }
        } else {
            return Err(ConfigCenterError::NotFound(
                format!("组件 '{}' 未找到", component_name)
            ));
        }
        
        Ok(())
    }
}

/// 日志配置监听器
pub struct LoggingConfigListener {
    name: String,
}

impl LoggingConfigListener {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

#[async_trait]
impl ConfigChangeListener for LoggingConfigListener {
    async fn on_config_change(&self, event: ConfigChangeEvent) -> ConfigCenterResult<()> {
        tracing::info!(
            "配置变更: {} - {} (来源: {:?})",
            event.config_key,
            match event.change_type {
                ConfigChangeType::Created => "创建",
                ConfigChangeType::Updated => "更新", 
                ConfigChangeType::Deleted => "删除",
                ConfigChangeType::Reloaded => "重载",
            },
            event.source
        );
        Ok(())
    }
    
    fn listener_name(&self) -> &str {
        &self.name
    }
}

/// 配置备份监听器
pub struct BackupConfigListener {
    name: String,
    backup_dir: PathBuf,
}

impl BackupConfigListener {
    pub fn new(name: String, backup_dir: PathBuf) -> Self {
        Self { name, backup_dir }
    }
}

#[async_trait]
impl ConfigChangeListener for BackupConfigListener {
    async fn on_config_change(&self, event: ConfigChangeEvent) -> ConfigCenterResult<()> {
        // 在配置变更时创建备份
        if matches!(event.change_type, ConfigChangeType::Updated | ConfigChangeType::Created) {
            let backup_file = self.backup_dir.join(format!(
                "config_{}_{}.json",
                event.config_key.replace('/', "_"),
                get_timestamp_string(&event.timestamp)
            ));
            
            if let Some(new_value) = &event.new_value {
                let backup_content = serde_json::to_string_pretty(new_value)
                    .map_err(|e| ConfigCenterError::Internal(format!("序列化备份失败: {}", e)))?;
                
                tokio::fs::write(&backup_file, backup_content).await
                    .map_err(|e| ConfigCenterError::Internal(format!("写入备份文件失败: {}", e)))?;
                
                tracing::info!("配置备份已保存: {:?}", backup_file);
            }
        }
        
        Ok(())
    }
    
    fn listener_name(&self) -> &str {
        &self.name
    }
}

/// 全局动态配置管理器实例
static GLOBAL_DYNAMIC_CONFIG_MANAGER: Lazy<DynamicConfigManager> = Lazy::new(|| {
    DynamicConfigManager::new(Duration::from_secs(300)) // 5分钟缓存TTL
});

/// 获取全局动态配置管理器
pub fn global_dynamic_config_manager() -> &'static DynamicConfigManager {
    &GLOBAL_DYNAMIC_CONFIG_MANAGER
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempfile::tempdir;
    use std::io::Write;

    #[tokio::test]
    async fn test_dynamic_config_manager() {
        let manager = DynamicConfigManager::new(Duration::from_secs(60));
        
        // 注册日志监听器
        let listener = Box::new(LoggingConfigListener::new("test_logger".to_string()));
        manager.register_listener(listener).await.unwrap();
        
        // 更新配置
        let config_value = serde_json::json!({"key": "value"});
        manager.update_config("test_component", "test_config", config_value).await.unwrap();
        
        // 验证缓存
        let cached = manager.get_cached_config("test_config").await;
        assert!(cached.is_some());
    }

    #[tokio::test]
    async fn test_config_change_event() {
        let event = ConfigChangeEvent {
            change_type: ConfigChangeType::Updated,
            config_key: "test_key".to_string(),
            old_value: Some(serde_json::json!("old")),
            new_value: Some(serde_json::json!("new")),
            timestamp: current_timestamp(),
            source: DynamicConfigSource::Api("test".to_string()),
            reason: "测试更新".to_string(),
        };
        
        assert_eq!(event.change_type, ConfigChangeType::Updated);
        assert_eq!(event.config_key, "test_key");
    }
}